-----------------------------------------------------------------------
-- File:        Env_Monitor.adb
-- Description: Containes procedures that analyze interrupts
--
-- Requires:    Swindows,Io_Ports,Unsigned_Types,Raildefs,Halls2,
--              Int32defs,Controllers
--
-- Author:     Ha Le
-----------------------------------------------------------------------
with Ada.Integer_Text_Io; --*
with Ada.Text_IO; --*
with Swindows;
use Swindows;
with Unsigned_Types;
use Unsigned_Types;  -- 1.8
with
   Raildefs,
   Int32defs,
   Halls2;
use Raildefs;
with Controllers;

package body Env_Monitor is --PROTECTED

   W_Interrupts : Swindows.Window;

   --  package Iio renames Ada.Integer_Text_Io;
   subtype String8 is String(1..8);  -- cant be declared in a protected.


   --Protected object declaration
   protected Interrupt is

      --Declaration of private functions and procedures

      --Analyze interrupts
      procedure Analyze (
            Offset : in     Raildefs.Sensor_Idx;
            -- 0 or 32
            Value : in     Raildefs.Four_Registers);-- vsn 2.0.5
      -- this procedure conforms to Raildefs.Proc4_Access

      --Output interrupt info to string
      function To_String (
            Val : Unsigned_8)
        return String8;

   private
      --Private members
      Number : Natural := 1;
      Line_Number : Natural := 1;
      Fg : Swindows.Color := Swindows.White;
      S : String(1..78) := (1..4|13|22|31|40|49|58|67|76..78 => ' ', others => '.');
      Result: String(1..64) := (others => '_');
   end Interrupt;


   --Body of protected object
   protected body Interrupt is

      -- this version just displays all the current states:
      -- it takes too much screen space

      --Analyze interrupt registers
      procedure Analyze (
            Offset : in     Raildefs.Sensor_Idx;
            Value  : in     Raildefs.Four_Registers) is
         --
         use Int32defs;
         V            : Sensor_Register;
         Sensor_Index : Natural;

      begin
         -- check to see whether int firing on OFF event
         -- it does!
         if Offset = 0 then
            Sensor_Index := 0; -- no offset
         else
            Sensor_Index := 32;
         end if;
         -- TRAIN CRASHED WHEN TOUCH SENSOR -- PROBLEM HERE -- FOUR REGISTERS actually 0..4
         for I in 0..3 loop  -- 0..3 bytes
            V := Unsigned_8_To_Sensor_Register(Value(I));
            for J in Sensor_Idx range 0..7 loop  -- note display LSB on left
               Sensor_Index:= Sensor_Index+1;
               if V(J) = Raildefs.On then
                  Result(Sensor_Index) := '0';
                  --Ada.Text_Io.Put_Line("On Sensor"&Sensor_Index'Img); --*
                  Controllers.Start_Sensor_Event(Raildefs.Sensor_Id(Sensor_Index),Raildefs.On);
                  -- Off just meant its not on, need to record which one just got ON
               else
                  if (Result(Sensor_Index) = '0') then -- prev on
                     --Ada.Text_Io.Put_Line("Prev On  00 Off Sensor"&Sensor_Index'Img); --*
                     Result(Sensor_Index) := '1';
                     Controllers.Start_Sensor_Event(Raildefs.Sensor_Id(Sensor_Index),Raildefs.Off);
                  else
                     Result(Sensor_Index) := '-';
                  end if;

               end if;
            end loop;
         end loop;



      exception
         when Constraint_Error =>
            null;
         when Tasking_Error =>
            null;
         when others =>
            null;
      end Analyze;

      --Output interrupt info to a string
      function To_String (
            Val : Unsigned_8)
        return String8 is
         use Int32defs;
         V      : Sensor_Register := Unsigned_8_To_Sensor_Register (Val);
         Result : String8         := "........";
      begin
         for I in Sensor_Idx range 0..7 loop  -- note display LSB on left
            if V(I) = Raildefs.On then
               Result(Integer(I)+1) := '0';
            else
               if V(I) = Raildefs.Off then
                  Result(Integer(I)+1) := '1';
               end if;
            end if;
         end loop;
         return Result;
      end To_String;

   end Interrupt;

   --Init Interrupts
   procedure Init (
         Win : in     Swindows.Window) is
   begin
      W_Interrupts := Win;
   end Init;

   --Install interrupt handling
   procedure Install is-- added v1.1
   begin
      Halls2.Install_Int_Handling(Interrupt.Analyze'access);
   end Install;

end Env_Monitor;
